#include <buola/gui.h>

#include <buola/widgets/csliderbox.h>
#include <buola/widgets/ctheme.h>

namespace buola { namespace gui {

CSliderBox::CSliderBox()
    :   mDragging(false),
        mInside(false)
{
    SetFocusMode(EFocusMode::TAB|EFocusMode::MOUSE);
    get_default_theme()->PrepareSliderBox(this);
    SetBackTransparent();

    SetPointer(CPointer::STOCK_DEFAULT);
}

CSliderBox::~CSliderBox()
{}

int CSliderBox::CalcPos()
{
    if(GetStyle(STYLE_HORIZONTAL))
        return SWMapToPos((int)(get_default_theme()->GetSliderSize()/2),
                          (int)(Size().x-get_default_theme()->GetSliderSize()/2));
    else
        return SWMapToPos((int)(get_default_theme()->GetSliderSize()/2),
                          (int)(Size().y-get_default_theme()->GetSliderSize()/2));
}

int CSliderBox::CalcValue(int pPos)
{
    if(GetStyle(STYLE_HORIZONTAL))
        return SWMapToValue((int)(get_default_theme()->GetSliderSize()/2),
                            (int)(Size().x-get_default_theme()->GetSliderSize()/2),pPos);
    else
        return SWMapToValue((int)(get_default_theme()->GetSliderSize()/2),
                            (int)(Size().y-get_default_theme()->GetSliderSize()/2),pPos);
}

///////////////////// Event handling //////////////////////

void CSliderBox::OnExpose(const CExposeEvent &pE)
{
    CTheme::EDrawStyle lFlags=CTheme::DRAW_NONE;
    if(mInside)
        lFlags|=CTheme::DRAW_HOVER;
    if(mDragging)
        lFlags|=CTheme::DRAW_HOVER|CTheme::DRAW_PRESSED;

    get_default_theme()->DrawSliderBox(pE.mGC,this,lFlags);
}

void CSliderBox::OnButtonDown(const CMouseEvent &pE)
{
    if(pE.mButton==EMouseButton::LEFT)
    {
        if(mDragging) return;
        int lClickPos;

        if(GetStyle(STYLE_HORIZONTAL))
            lClickPos=(int)pE.mPoint.x;
        else
            lClickPos=(int)pE.mPoint.y;
                  
        int lCurPos=CalcPos();
        if(abs(lCurPos-lClickPos)<get_default_theme()->GetSliderSize()/2)
        {
            mDragStart=lClickPos;
            mDragPos=mDragStart;
            mDragging=true;

            Refresh();
        }
        else
        {
            SetValue(CalcValue(lClickPos));
        }
    }
}

void CSliderBox::OnButtonUp(const CMouseEvent &pE)
{
    if(!mDragging) return;
    mDragging=false;

    Refresh();    
}

void CSliderBox::OnMouseIn(const CMouseEvent &pE)
{
    mInside=true;
    Refresh();
}

void CSliderBox::OnMouseOut(const CMouseEvent &pE)
{
    mInside=false;
    Refresh();
}

void CSliderBox::OnMouseMove(const CMouseEvent &pE)
{
    if(!mDragging) return;

    int lPos;

    if(GetStyle(STYLE_HORIZONTAL))
        lPos=(int)pE.mPoint.x;
    else
        lPos=(int)pE.mPoint.y;
                
    if(lPos==mDragPos) return;
    mDragPos=lPos;

    SetValue(CalcValue(mDragPos));
}

void CSliderBox::OnMouseWheel(const CMouseEvent &pE)
{
    if(pE.mScrollY!=0)
        IncValue(pE.mScrollY*GetBigStep());
}

void CSliderBox::OnFocusIn(const CFocusEvent &pE)
{
}

void CSliderBox::OnFocusOut(const CFocusEvent &pE)
{
}

void CSliderBox::OnKeyDown(const CKeyEvent &pE)
{
    int lInc=0;

    if(GetStyle(STYLE_HORIZONTAL))
    {
        if(pE.mKey==KEY_LEFT)
        {
            if(pE.mMods&KEYMOD_SHIFT)
                lInc=-GetBigStep();
            else
                lInc=-GetSmallStep();
        }
        if(pE.mKey==KEY_RIGHT)
        {
            if(pE.mMods&KEYMOD_SHIFT)
                lInc=GetBigStep();
            else
                lInc=GetSmallStep();
        }
    }
    else
    {
        if(pE.mKey==KEY_UP)
        {
            if(pE.mMods&KEYMOD_SHIFT)
                lInc=-GetBigStep();
            else
                lInc=-GetSmallStep();
        }
        if(pE.mKey==KEY_DOWN)
        {
            if(pE.mMods&KEYMOD_SHIFT)
                lInc=GetBigStep();
            else
                lInc=GetSmallStep();
        }
    }
        
    IncValue(lInc);
}

void CSliderBox::OnStyleChanged(TStyle pOld)
{
    int lChange=pOld^GetStyle();
    
    if(lChange&STYLE_FAKE)
    {
        if(GetStyle(STYLE_FAKE))
        {
            SetInputMode(EInputMode::MOUSETRANSPARENT);
        }
        else
        {
            SetInputMode(EInputMode::NORMAL);
        }
    }
    if(lChange&STYLE_HORIZONTAL)
    {
        Refresh();
    }
}

void CSliderBox::OnSWChange()
{
    Refresh();
}

/*namespace gui*/ } /*namespace buola*/ }
